﻿using Autofac;
using Autofac.Extras.Quartz;
using log4net;
using Microsoft.Extensions.Configuration;
using Quartz;
using Quartz.Impl;
using Quartz.Spi;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using WLYT.Common;

namespace WLYT.Admin.WebApi.Component.Quartz
{
    /// <summary>
    /// 任务调度中心
    /// </summary>
    public class SchedulerCenter    
    {

        /// <summary>
        /// 任务计划
        /// </summary>
        public IScheduler scheduler = null;
        public async Task<IScheduler> GetSchedulerAsync()
        {
            if (scheduler != null)
            {
                return scheduler;
            }
            else
            {
                // 从Factory中获取Scheduler实例
                NameValueCollection props = new NameValueCollection
                {                    
                    ["quartz.scheduler.instanceName"] = "TestScheduler",//scheduler名字
                    ["quartz.serializer.type"] = "json",//json,切换为数据库存储的时候需要设置json
                    ["quartz.scheduler.instanceId"] = "AUTO",//自动生成scheduler实例ID，主要为了保证集群中的实例具有唯一标识
                    ["quartz.jobStore.clustered"] = "true",//是否配置集群
                    ["quartz.threadPool.threadCount"] = "20", //线程池个数
                    //以下配置需要数据库表配合使用，表结构sql地址：https://github.com/quartznet/quartznet/tree/master/database/tables
                    ["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",//类型为JobStoreXT,事务
                    //["quartz.jobStore.useProperties"] = "true", //JobDataMap中的数据都是字符串
                    ["quartz.jobStore.dataSource"] = "LCKT_WMS", //数据源名称
                    ["quartz.jobStore.tablePrefix"] = "QRTZ_",//数据表名前缀
                    ["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz",//使用Sqlserver的Ado操作代理类
                    ["quartz.dataSource.LCKT_WMS.connectionString"] = ConfigExtensions.Configuration.GetConnectionString("wmsConnection"), //数据源连接字符串
                    ["quartz.dataSource.LCKT_WMS.provider"] = "SqlServer" //数据源的数据库
                };
                StdSchedulerFactory factory = new StdSchedulerFactory(props);
                return await factory.GetScheduler();

            }
        }

        /// <summary>
        /// 添加调度任务
        /// </summary>
        /// <param name="infoDto"></param>
        /// <returns></returns>
        public async Task<bool> AddTaskAsync(WLYT.Domain.Model.Task infoDto)
        {
            try
            {
                if (infoDto != null)
                {

                    infoDto.CreateTime = DateTime.Now;
                    DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(infoDto.CreateTime, 1);
                    //if (infoDto.EndTime == null)
                    //{
                    //    infoDto.EndTime = DateTime.MaxValue.AddDays(-1);
                    //}
                    //DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(infoDto.EndTime, 1);
                    scheduler = await GetSchedulerAsync();
                    JobKey jobKey = new JobKey(infoDto.TaskName);
                    if (await scheduler.CheckExists(jobKey))
                    {
                        await scheduler.PauseJob(jobKey);
                        await scheduler.DeleteJob(jobKey);
                    }
                    IJobDetail job = JobBuilder.Create<CronTask>().WithIdentity(jobKey).Build();
                    ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
                                                 .StartAt(starRunTime)
                                                 //.EndAt(endRunTime)
                                                 .WithIdentity(infoDto.TaskName)
                                                 .WithCronSchedule(infoDto.CronExpress)
                                                 .Build();
                    scheduler.JobFactory = AutofacConfig._container.Resolve<IJobFactory>(); 
                    await scheduler.ScheduleJob(job, trigger);
                    await scheduler.Start();
                    return true;
                }

                return false;//JobInfo为空
            }
            catch (Exception ex)
            {
                return false;//出现异常
            }
        }

        /// <summary>
        /// 暂停指定任务计划
        /// </summary>
        /// <param name="jobName">任务名</param>
        /// <returns></returns>
        public async Task<bool> StopTaskAsync(string jobName)
        {
            try
            {
                JobKey jobKey = new JobKey(jobName);
                scheduler = await GetSchedulerAsync();
                if (await scheduler.CheckExists(jobKey))
                {
                    await scheduler.PauseJob(jobKey);
                    return true;
                }
                else
                {
                    return false;//任务不存在
                }
            }
            catch (Exception ex)
            {
                return false;//出现异常
            }
        }

        /// <summary>
        /// 恢复指定的任务计划,如果是程序奔溃后 或者是进程杀死后的恢复，此方法无效
        /// </summary>
        /// <param name="jobName">任务名称</param>
        /// <returns></returns>
        public async Task<bool> ResumeTaskAsync(string jobName)
        {
            try
            {
                JobKey jobKey = new JobKey(jobName);
                scheduler = await GetSchedulerAsync();
                if (await scheduler.CheckExists(jobKey))
                {
                    //resumejob 恢复
                    await scheduler.ResumeJob(jobKey);
                    return true;
                }
                else
                {
                    return false;//不存在任务
                }

            }
            catch (Exception ex)
            {
                return false;//出现异常
            }
        }

        /// <summary>
        /// 恢复指定的任务计划,如果是程序奔溃后 或者是进程杀死后的恢复，此方法无效
        /// </summary>
        /// <param name="jobName">任务名称</param>
        /// <returns></returns>
        public async Task<bool> DeleteTaskAsync(string jobName)
        {
            try
            {
                JobKey jobKey = new JobKey(jobName);
                scheduler = await GetSchedulerAsync();
                if (await scheduler.CheckExists(jobKey))
                {
                    //DeleteJob 恢复
                    await scheduler.DeleteJob(jobKey);
                    return true;
                }
                else
                {
                    return false;//不存在任务
                }

            }
            catch (Exception ex)
            {
                return false;//出现异常
            }
        }
    }
}